package hotel.base.oversea.utils;


import cn.hutool.json.JSONUtil;
import hotel.base.oversea.constant.CommonConstants;
import hotel.base.oversea.dto.BaseAuthResultDto;
import hotel.base.oversea.constant.CommonUrlConstants;
import hotel.base.oversea.utils.redis.JedisPoolUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.util.ObjectUtils;

import java.io.IOException;
import java.util.*;
import java.util.concurrent.*;

@Slf4j
public class HttpClientBaseAuth {

    public static String username = "client";
    public static String password = "123456";
    //todo

//    public static String uri ="http://localhost:4000/oauth/token";
//    public static String delToken ="http://localhost:4000/token/logout";

    public static String uri = CommonUrlConstants.AUTH_HOST + "/oauth/token";
    public static String delToken =CommonUrlConstants.AUTH_HOST + "/token/logout";

    //加密
    public static BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();


    public static void main(String[] arg){
//        for(int i=0;i<50;i++){
//            BaseAuthResultDto baseAuthResultDto = httpClientWithBasicAuth();
//            if(ObjectUtils.isEmpty(baseAuthResultDto.getAccess_token())){
//                log.info("getAccess_token>>>>>为空");
//            }else{
//                log.info("AccessToken{}",baseAuthResultDto.getAccess_token());
//            }
////            log.info(getAuthToken());
//        }

//        log.info("count=== {}",count);
//        try {
//            getThread();
//        } catch (ExecutionException e) {
//            e.printStackTrace();
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }

//        String url = "";
//
//        int taskSize = 60;//总线程数量 20的倍数
//
//        int voidSize = 20;//总调用方法数量
//        int page = 5;
//        int forInt = taskSize/voidSize;
//        int tempPage = 0;//5
//        int temp = page;
//        for(int n=1;n<=forInt;n++){
//            log.info(" n -------->>>> {} ",n);
//            for (int i = 1; i <= 20; i++) {
//                tempPage = temp  + i;
//                if(tempPage == temp){
//                    continue;
//                }
//                log.info("temp >>>> {}   i>>>> {}   tempPage>>>>>>> {} ",temp,i,tempPage);
////                Callable c = new SpiderCallable(String.valueOf(i),tempPage,totalPage);
////             执行任务并获取Future对象
////                Future f = pool.submit(c);
////             单个查询返回的Future
////                list.add(f);
//                if(i == (voidSize)){
//                    temp = tempPage;
//                }
//            }
//        }


//        if("1078761921SMS".indexOf("SMS") != -1){
//            log.info("存在sms");
//        }

//        log.info("quartz-hhb888:{}",passwordEncoder.encode("quartz-hhb888"));//$2a$10$4j4ihwgperFOUVi0BtAPUeaeMGcWJmY4KndbIn3HdiykYHC74ux7W
//        log.info("switchs-hhb888:{}",passwordEncoder.encode("switchs-hhb888"));//$2a$10$ctSSqXp12VhsNjrlNckXzeiNuA1aAE8uDzR2vEnHD0u.fvyu8ion2
//        log.info("meituan-hhb888:{}",passwordEncoder.encode("meituan-hhb888"));//$2a$10$2sfe3hOKNk4asFMrfh.rWOkRGivqlaneqU5YH7y1ZRDLilliuMLOm
//        log.info("callback-hhb888:{}",passwordEncoder.encode("callback-hhb888"));//$2a$10$vOvZyW5fQ8NrosVKzD0ubesf/Bf.J5dmbMEEToRPU6seTWrwG2i.W
        log.info("fpadmin-hhb888:{}",passwordEncoder.encode("fpadmin-hhb888"));//$2a$10$swiLzi4MuSaFHJhk0KTu.Oq73E/pvEMsPABWpkY1nzdnbM16TLsJW

    }



    public static String getAuthToken(){
        BaseAuthResultDto baseAuthResultDto = httpClientWithBasicAuth();
        String retToken = baseAuthResultDto.getAccess_token();
        int count = 0;
        log.info("token:{} 工具类-首次获取token 对应剩余时间expiresIn--->{}",retToken,baseAuthResultDto.getExpires_in());
        while (ObjectUtils.isEmpty(retToken) && count<=10){
            count++;
            baseAuthResultDto = httpClientWithBasicAuth();

            if(!ObjectUtils.isEmpty(baseAuthResultDto.getAccess_token())){
                retToken = baseAuthResultDto.getAccess_token();
            }

            log.info("循环：{} ；token工具获取返回值：{}，token:{}",count,baseAuthResultDto,retToken);
        }
        log.info("循环：{} ；token工具类：获取token 对应剩余时间expiresIn--->{}",count,baseAuthResultDto.getExpires_in());
        return retToken;
    }

    public static BaseAuthResultDto httpClientWithBasicAuth() {
        Map<String, String> paramMap = new HashMap<>();
        paramMap.put("grant_type", "password");
        paramMap.put("username", "hotel");
        paramMap.put("password", "hotel-hhb888");
        String result = "";
        try {
            // 创建HttpClientBuilder
            HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
            CloseableHttpClient closeableHttpClient = httpClientBuilder.build();
            HttpPost httpPost = new HttpPost(uri);
            //添加http头信息
            httpPost.addHeader("Authorization", "Basic " + Base64.getUrlEncoder().encodeToString((username + ":" + password).getBytes()));
            MultipartEntityBuilder builder = MultipartEntityBuilder.create();
            paramMap.forEach((k, v) -> {
                builder.addPart(k, new StringBody(v, ContentType.MULTIPART_FORM_DATA));
            });
            HttpEntity postEntity = builder.build();
            httpPost.setEntity(postEntity);
            HttpResponse httpResponse = null;
            HttpEntity entity = null;
            try {
                httpResponse = closeableHttpClient.execute(httpPost);
                entity = httpResponse.getEntity();
                if (entity != null) {
                    result = EntityUtils.toString(entity);
                }
            } catch (ClientProtocolException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            // 关闭连接
            closeableHttpClient.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        BaseAuthResultDto baseAuthResultDto = JSONUtil.toBean(result,BaseAuthResultDto.class);
//        log.info("baseAuthResultDto{}",baseAuthResultDto);

//        String accessToken = baseAuthResultDto.getAccess_token();
//        String expiresIn = baseAuthResultDto.getExpires_in();
//        if(!ObjectUtils.isEmpty(expiresIn) && Integer.valueOf(expiresIn) < 100){
//            boolean ret = delToken(accessToken);
//            if(ret){
//                baseAuthResultDto = httpClientWithBasicAuth();
//            }
//        }

        return baseAuthResultDto;
    }

    /**
     * 根据模块名称获取对应token
     * @param appname
     * @return
     */
    public static String getAuthTokenByAppname(String appname){
        String appKey = appname+"_token";
        String retToken = JedisPoolUtil.get(appKey);
        if(!ObjectUtils.isEmpty(retToken) ){
            log.info("从redis 获取 retToken:{} ",retToken);
            return retToken;
        }
        BaseAuthResultDto baseAuthResultDto = httpClientWithBasicAuthByAppname(appname);
        retToken = baseAuthResultDto.getAccess_token();
        int count = 0;
        log.info("token:{} 工具类-首次获取token 对应剩余时间expiresIn--->{}",retToken,baseAuthResultDto.getExpires_in());
        while (ObjectUtils.isEmpty(retToken) && count<=10){
            count++;
            baseAuthResultDto = httpClientWithBasicAuthByAppname(appname);

            if(!ObjectUtils.isEmpty(baseAuthResultDto.getAccess_token())){
                retToken = baseAuthResultDto.getAccess_token();
            }


            log.info("循环：{} ；token工具获取返回值：{}，token:{}",count,baseAuthResultDto,retToken);
        }
        if(!ObjectUtils.isEmpty(retToken)){
            JedisPoolUtil.setex(appKey,retToken,Integer.valueOf(baseAuthResultDto.getExpires_in()));
        }
//        log.info("循环：{} ；token工具类：获取token 对应剩余时间expiresIn--->{}",count,baseAuthResultDto.getExpires_in());
        return retToken;
    }

    /**
     * 根据模块获取token
     * @param appname
     * @return
     */
    public static BaseAuthResultDto httpClientWithBasicAuthByAppname(String appname) {
        Map<String, String> paramMap = new HashMap<>();
        paramMap.put("grant_type", "password");

        //定时任务
        if("sec-quartz".equals(appname)){
            paramMap.put("username", "sec-quartz");
            paramMap.put("password", "quartz-hhb888");
        }else if("sec-switchs".equals(appname)){//携程
            paramMap.put("username", "sec-switchs");
            paramMap.put("password", "switchs-hhb888");
        }else if("sec-meituan".equals(appname)){//美团
            paramMap.put("username", "sec-meituan");
            paramMap.put("password", "meituan-hhb888");
        }else if("sec-callback".equals(appname)){
            paramMap.put("username", "sec-callback");
            paramMap.put("password", "callback-hhb888");
        }
        //飞猪相关
        else if("fp-callback".equals(appname)){
            paramMap.put("username", "fp-callback");
            paramMap.put("password", "fp-callback-hhb888");
        }else if("fp-channel".equals(appname)){
            paramMap.put("username", "fp-channel");
            paramMap.put("password", "fp-channel-hhb888");
        }else if("fp-meituan".equals(appname)){
            paramMap.put("username", "fp-meituan");
            paramMap.put("password", "fp-meituan-hhb888");
        }else if("switchs-can".equals(appname)){
            paramMap.put("username", "switchs-can");
            paramMap.put("password", "switchs-can-hhb888");
        }else if("fpadmin".equals(appname)){
            paramMap.put("username", "fpadmin");
            paramMap.put("password", "fpadmin-hhb888");
        }
        //携程二线
        else{//其他默认hotel
            paramMap.put("username", "hotel");
            paramMap.put("password", "hotel-hhb888");
        }
        String result = "";
        try {
            // 创建HttpClientBuilder
            HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
            CloseableHttpClient closeableHttpClient = httpClientBuilder.build();
            HttpPost httpPost = new HttpPost(uri);
            //添加http头信息
            httpPost.addHeader("Authorization", "Basic " + Base64.getUrlEncoder().encodeToString((username + ":" + password).getBytes()));
            MultipartEntityBuilder builder = MultipartEntityBuilder.create();
            paramMap.forEach((k, v) -> {
                builder.addPart(k, new StringBody(v, ContentType.MULTIPART_FORM_DATA));
            });
            HttpEntity postEntity = builder.build();
            httpPost.setEntity(postEntity);
            HttpResponse httpResponse = null;
            HttpEntity entity = null;
            try {
                httpResponse = closeableHttpClient.execute(httpPost);
                entity = httpResponse.getEntity();
                if (entity != null) {
                    result = EntityUtils.toString(entity);
                }
            } catch (ClientProtocolException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            // 关闭连接
            closeableHttpClient.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        BaseAuthResultDto baseAuthResultDto = JSONUtil.toBean(result,BaseAuthResultDto.class);
        return baseAuthResultDto;
    }


    /**
     * 根据用户名密码获取token
     * @param username
     * @param password
     * @return
     */
    public static BaseAuthResultDto httpClientWithBasicAuth(String username,String password) {
        Map<String, String> paramMap = new HashMap<>();
        paramMap.put("grant_type", "password");
        paramMap.put("username", username);
        paramMap.put("password", password);
        String result = "";
        try {
            // 创建HttpClientBuilder
            HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
            CloseableHttpClient closeableHttpClient = httpClientBuilder.build();
            HttpPost httpPost = new HttpPost(uri);
            //添加http头信息
            httpPost.addHeader("Authorization", "Basic " + Base64.getUrlEncoder().encodeToString((username + ":" + password).getBytes()));
            MultipartEntityBuilder builder = MultipartEntityBuilder.create();
            paramMap.forEach((k, v) -> {
                builder.addPart(k, new StringBody(v, ContentType.MULTIPART_FORM_DATA));
            });
            HttpEntity postEntity = builder.build();
            httpPost.setEntity(postEntity);
            HttpResponse httpResponse = null;
            HttpEntity entity = null;
            try {
                httpResponse = closeableHttpClient.execute(httpPost);
                entity = httpResponse.getEntity();
                if (entity != null) {
                    result = EntityUtils.toString(entity);
                }
            } catch (ClientProtocolException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            // 关闭连接
            closeableHttpClient.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        BaseAuthResultDto baseAuthResultDto = JSONUtil.toBean(result,BaseAuthResultDto.class);
        return baseAuthResultDto;
    }

    public static boolean delToken(String token){
        boolean ret = false;
        String result = "";
        try {
            // 创建HttpClientBuilder
            HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
            CloseableHttpClient closeableHttpClient = httpClientBuilder.build();
            HttpDelete httpDelete = new HttpDelete(delToken);
            //添加http头信息
            httpDelete.addHeader("Authorization", "bearer " + token);
            HttpResponse httpResponse = null;
            HttpEntity entity = null;
            try {
                httpResponse = closeableHttpClient.execute(httpDelete);
                entity = httpResponse.getEntity();
                if (entity != null) {
                    result = EntityUtils.toString(entity);
                }
            } catch (ClientProtocolException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            // 关闭连接
            closeableHttpClient.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

        Result resultDto = JSONUtil.toBean(result,Result.class);
        if(resultDto.getCode() == CommonConstants.SUCCESS){
            ret = true;
        }
        return  ret;
    }

    public static void getThread() throws ExecutionException, InterruptedException {
        System.out.println("----程序开始运行----");
        Date date1 = new Date();

        int taskSize = 5;
        // 创建一个线程池
        ExecutorService pool = Executors.newFixedThreadPool(taskSize);
        // 创建多个有返回值的任务
        List<Future> list = new ArrayList<Future>();
        for (int i = 0; i < taskSize; i++) {
            Callable c = new MyCallable(i + " ");
            // 执行任务并获取Future对象
            Future f = pool.submit(c);
            // System.out.println(">>>" + f.get().toString());
            list.add(f);
        }
        // 关闭线程池
        pool.shutdown();

        // 获取所有并发任务的运行结果
        for (Future f : list) {
            // 从Future对象上获取任务的返回值，并输出到控制台
            System.out.println(">>>" + f.get().toString());
        }

        Date date2 = new Date();
        System.out.println("----程序结束运行----，程序运行时间【"
                + (date2.getTime() - date1.getTime()) + "毫秒】");
    }

    static class MyCallable implements Callable<Object> {
        private String taskNum;

        MyCallable(String taskNum) {
            this.taskNum = taskNum;
        }

        @Override
        public Object call() throws Exception {
            System.out.println(">>>" + taskNum + "任务启动");
            Date dateTmp1 = new Date();
            Thread.sleep(1000);
            BaseAuthResultDto baseAuthResultDto = httpClientWithBasicAuth();
            if(ObjectUtils.isEmpty(baseAuthResultDto.getAccess_token())){
                log.info("getAccess_token>>>>>为空");
            }else{
                log.info("AccessToken{}",baseAuthResultDto.getAccess_token());
            }
            Date dateTmp2 = new Date();
            long time = dateTmp2.getTime() - dateTmp1.getTime();
            System.out.println(">>>" + taskNum + "任务终止");
            return taskNum + "任务返回运行结果,当前任务时间【" + time + "毫秒】";
        }
    }

}
